﻿/*  ------------------------------------------------------------------------
	 NQ Common Services Library
	 
	 Homepage: http://www.awzhome.de/
	 ------------------------------------------------------------------------
	 
	 The contents of this file are subject to the Mozilla Public License
	 Version 1.1 (the "License"); you may not use this file except in
	 compliance with the License. You may obtain a copy of the License at
	 http://www.mozilla.org/MPL/
	 
	 Software distributed under the License is distributed on an "AS IS"
	 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	 License for the specific language governing rights and limitations
	 under the License.
	
	 The Original Code is code of NQ Common Services Library.

	 The Initial Developer of the Original Code is Andreas Weizel.
	 Portions created by the Initial Developer are
	 Copyright (C) 2006-2012 Andreas Weizel. All Rights Reserved.
	 
	 Contributor(s): (none)
	 
	 Alternatively, the contents of this file may be used under the terms
	 of the GNU General Public License Version 2.0 or later (the "GPL"),
	 or the GNU Lesser General Public License Version 2.1 or later (the
	 "LGPL"), in which case the provisions of the GPL or the LGPL are
	 applicable instead of those above. If you wish to allow use of your
	 version of this file only under the terms of the GPL or the LGPL and
	 not to allow others to use your version of this file under the MPL,
	 indicate your decision by deleting the provisions above and replace
	 them with the notice and other provisions required by the GPL or the
	 LGPL. If you do not delete the provisions above, a recipient may use
	 your version of this file under the terms of any of the MPL, the GPL
	 or the LGPL.
	 ------------------------------------------------------------------------
*/

using System;
using AWZhome.NQ.Core;
using AWZhome.NQ.Core.Fluent;
using AWZhome.NQ.CommonServices.Visual;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Interop;
using System.Windows.Forms.Integration;
using System.Runtime.InteropServices;

namespace AWZhome.NQ.CommonServices
{

	[NQExportedService]
	internal partial class MainContainerService : Services.IMainContainerService
	{
		private IBarManager _servBar;
		private IViewManager _servViewManager = null;
		private IPersistManager _servPersist;

		private MainContainerWindow _window = null;
		private IntPtr _windowHandle;

		private string _windowText;
		private string _name;
		private object _clientAreaObject = null;

		public event EventHandler ContainerOpened;
		public event EventHandler ContainerClosed;

		[DllImport("user32.dll")]
		private static extern bool FlashWindow(IntPtr hwnd, bool bInvert);

		#region INQContainerService Members

		public void Initialize(string name)
		{
			this._name = name;

			// Create the window
			_window = new MainContainerWindow();
			_windowHandle = (new WindowInteropHelper(_window)).Handle;

			// Set event handlers for the container window
			_window.Loaded += new RoutedEventHandler(_window_Loaded);
			_window.ContainerClosing += new EventHandler(_window_ContainerClosing);

			_servPersist = ServiceCore
				.Get<Services.IPersistService>()
				.To;

			// Initialize view manager and bar services
			_servBar = ServiceCore
				.Create<Services.IBarService>()
				.To;
			_servBar.InitBarService(_window, name, this);
			_servBar.DockLeft = true;
			_servBar.DockRight = true;
			_servBar.DockBottom = true;

			// Create menu and status bars
			_servBar.CreateMenuBar();
			_servBar.CreateStatusBar();

			// Load main menu service
			ServiceCore
				.Create<Services.IMainMenuService>()
				.DependentOn<IContainer>(this);

			// Initialize the view manager
			_servViewManager = ServiceCore
				.Create<Services.IViewManagerService>()
				.DependentOn<IContainer>(this)
				.To;

			// Note: All further initialization is done in LoadContainer() after _window.Loaded event has been raised

			// Show the window
			_window.Show();
		}

		public void FlashWindow()
		{
			// Flash the window in task bar
			FlashWindow(_windowHandle, true);
		}

		public void FocusWindow()
		{
			// Set focus on this window
			_window.Activate();
		}

		public bool ShowModalDialog(object dialog)
		{
			if (dialog is Window)
			{
				// Dialog is a WPF window
				((Window) dialog).Owner = _window;
				return ((Window) dialog).ShowDialog().Value;
			}
			else if (dialog is System.Windows.Forms.Form)
			{
				// Dialog is a WinForms window
				return (((System.Windows.Forms.Form) dialog).ShowDialog() == System.Windows.Forms.DialogResult.OK);
			}
			else
			{
				return false;
			}
		}

		public void AddControl(object control)
		{
			// Add the control to form
			if (control is System.Windows.Controls.Control)
			{
				_window.InnerGrid.Children.Add((UIElement) control);
			}
			else if (control is System.Windows.Forms.Control)
			{
				WindowsFormsHost winFormsHost = new WindowsFormsHost();
				winFormsHost.Child = (System.Windows.Forms.Control) control;
				winFormsHost.Margin = new Thickness(0, 0, 0, 0);
				_window.InnerGrid.Children.Add(winFormsHost);
			}
		}

		public void RemoveControl(object control)
		{
			// Drop control from form
			if (control is System.Windows.Controls.Control)
			{
				_window.InnerGrid.Children.Remove((UIElement) control);
			}
			else if (control is System.Windows.Forms.Control)
			{
				if ((control is Control) && (((Control) control).Parent is WindowsFormsHost))
				{
					WindowsFormsHost winFormsHost = (WindowsFormsHost) ((Control) control).Parent;
					((Grid) winFormsHost.Parent).Children.Remove(winFormsHost);
					winFormsHost = null;
				}
				else
				{
					throw new ArgumentException("Windows Forms control has no WindowsFormsHost as container.", "control");
				}
			}
		}

		public void Update()
		{
			// Set window caption and icon depending on the active view
			if (this.ViewManager.ActiveView != null)
			{
				this.WindowText = this.ViewManager.ActiveView.DisplayName;
				ISession viewsSession = this.ViewManager.ActiveView.Session;
				if (viewsSession != null)
				{
					this.WindowText += " - " + this.ViewManager.ActiveView.Session.DisplayName;
				}
				this.WindowIcon = this.ViewManager.ActiveView.Icon;
			}
			else
			{
				// Show default session's display name
				this.SetDefaultWindowText();
				this.WindowIcon = null;
			}
		}

		public IBarManager BarService
		{
			get
			{
				return _servBar;
			}
		}

		public IViewManager ViewManager
		{
			get
			{
				return _servViewManager;
			}
		}

		public string WindowText
		{
			get
			{
				return _windowText;
			}
			set
			{
				_windowText = value ?? "";
				_window.Title = _windowText;
			}
		}

		public IntPtr WindowHandle
		{
			get
			{
				return _windowHandle;
			}
		}

		public ImageSource WindowIcon
		{
			get
			{
				return _window.Icon;
			}
			set
			{
				_window.Icon = value;
			}
		}

		public object ClientAreaObject
		{
			get
			{
				if (_clientAreaObject == null)
				{
					return _window.InnerGrid;
				}
				else
				{
					return _clientAreaObject;
				}
			}
			set
			{
				_clientAreaObject = value;
			}
		}

		public string Name
		{
			get
			{
				return _name;
			}
		}

		public int WindowTop
		{
			get
			{
				return (int) _window.Top;
			}
			set
			{
				_window.Top = value;
			}
		}
		public int WindowLeft
		{
			get
			{
				return (int) _window.Left;
			}
			set
			{
				_window.Left = value;
			}
		}
		public int WindowWidth
		{
			get
			{
				return (int) _window.Width;
			}
			set
			{
				_window.Width = value;
			}
		}
		public int WindowHeight
		{
			get
			{
				return (int) _window.Height;
			}
			set
			{
				_window.Height = value;
			}
		}

		#endregion

		#region Event handlers

		private void _window_Loaded(object sender, RoutedEventArgs e)
		{
			LoadContainer();
		}

		private void _window_ContainerClosing(object sender, EventArgs e)
		{
			EndContainer(e);
		}

		#endregion

		#region Other private methods

		private void LoadContainer()
		{
			// Set window state
			ConfigData windowstate = _servPersist.GetContainerSetting(this._name, "windowState");
			if (windowstate.AsString("1") == "1")
			{
				// A maximized window has its own bounds setting -> read it to maximize the window
				ConfigData windowrectmaxData = _servPersist.GetContainerSetting(this._name, "windowRectMax");
				if (windowrectmaxData != null)
				{
					Rect windowrectmax = windowrectmaxData.AsRect().Value;
					_window.Top = windowrectmax.Top;
					_window.Left = windowrectmax.Left;
					_window.Height = windowrectmax.Height;
					_window.Width = windowrectmax.Width;
				}
				_window.WindowState = WindowState.Maximized;
			}
			else if (windowstate.AsString("2") == "2")
			{
				_window.WindowState = WindowState.Minimized;
			}
			else
			{
				// Use normal bound setting
				ConfigData windowrectData = _servPersist.GetContainerSetting(this._name, "windowRect");
				if (!windowrectData.IsEmpty)
				{
					Rect windowrect = windowrectData.AsRect().Value;
					_window.Top = windowrect.Top;
					_window.Left = windowrect.Left;
					_window.Height = windowrect.Height;
					_window.Width = windowrect.Width;
				}
				else
				{
					// Default bounds rectangle
					Rect defrect = SystemParameters.WorkArea;
					defrect.Inflate(-50, -50);
					_window.Top = defrect.Top;
					_window.Left = defrect.Left;
					_window.Height = defrect.Height;
					_window.Width = defrect.Width;
				}
			}

			// Load all bar settings
			_servBar.LoadBarSettings();

			// Load all attached services (mostly for menu and toolbar creation)
			ServiceCore
				.RetrieveAttached<object>(CommonAttachLists.MainContainer_Startup)
				.DependentOn<IContainer>(this);

			// Temporarily show the default session title as the window title
			SetDefaultWindowText();

			// Load view manager settings
			_servViewManager.LoadSettings();

			// Raise ContainerOpened event
			if (this.ContainerOpened != null)
			{
				this.ContainerOpened(this, new EventArgs());
			}
		}

		private void SetDefaultWindowText()
		{
			// Get the default session service and use its title as the window text
			ISessionManager sessionManServ = ServiceCore
				.Get<Services.ISessionManagerService>()
				.To;
			if (sessionManServ.DefaultSession != null)
			{
				this.WindowText = sessionManServ.DefaultSession.DisplayName;
			}
			else
			{
				// We have to other chance...
				this.WindowText = "NQ";
			}
		}

		private void EndContainer(EventArgs e)
		{
			// Save settings
			try
			{
				ConfigData windowRectData = new ConfigData().FromRect(new Rect(_window.Left, _window.Top, _window.Width, _window.Height));
				if (_window.WindowState == WindowState.Normal)
				{
					_servPersist.SetContainerSetting(this._name, "windowRect", windowRectData);
					_servPersist.SetContainerSetting(this._name, "windowState", new ConfigData().FromInt32(0));
				}
				else if (_window.WindowState == WindowState.Maximized)
				{
					_servPersist.SetContainerSetting(this._name, "windowRectMax", windowRectData);
					_servPersist.SetContainerSetting(this._name, "windowState", new ConfigData().FromInt32(1));
				}
				else if (_window.WindowState == WindowState.Minimized)
				{
					_servPersist.SetContainerSetting(this._name, "windowState", windowRectData);
				}

				// Save bar settings
				_servBar.SaveBarSettings();

				// Save view manager settings
				_servViewManager.SaveSettings();
			}
			catch (Exception ex)
			{
				ServiceCore.Log.From(this).Error(ex);
			}

			// Raise ContainerClosed event
			if (this.ContainerClosed != null)
			{
				this.ContainerClosed(this, e);
			}
		}

		private int ViewManIndexFromType(ViewDisplayMode displayMode)
		{
			switch (displayMode)
			{
				case ViewDisplayMode.InClientArea:
					return 0;
				case ViewDisplayMode.DockedLeft:
					return 1;
				case ViewDisplayMode.DockedRight:
					return 2;
				case ViewDisplayMode.Floating:
					return 3;
				default:
					return 0;
			}
		}

		private ViewDisplayMode ViewTypeFromViewManIndex(int index)
		{
			switch (index)
			{
				case 0:
					return ViewDisplayMode.InClientArea;
				case 1:
					return ViewDisplayMode.DockedLeft;
				case 2:
					return ViewDisplayMode.DockedRight;
				case 3:
					return ViewDisplayMode.Floating;
				default:
					return ViewDisplayMode.Floating;
			}
		}

		#endregion

	}

}